我們的短期目標是,在網頁上用純文字的方式直接顯示遊戲狀態
並會隨著遊戲更新的時候更新
原本想要把 遊戲 存在房間裡面,但是在這邊已經不需要其他房間的功能了,多一層很煩
我就直接在 ETS 再開另一個表格 叫 games 然後用跟房間一樣的 id 來儲存遊戲狀態
在 lib/card/application.ex
裡面加在之前的 rooms 表格後面
# 建立 rooms 與 games table 給大家用
:ets.new(:rooms, [:set, :public, :named_table])
:ets.new(:games, [:set, :public, :named_table])
開始寫這一頁的 mount 方法吧
要做的事情有
我們先把發牌員做好
新開一個檔案/lib/card/dealer.ex
defmodule Card.Dealer do
use GenServer
def init(_) do
{:ok, []}
end
def handle_call(id, _from, games) do
case :ets.lookup(:games, id) do
[{^id, pid}] -> {:reply, {id, pid}, games}
[] ->
{:ok, pid} = Card.Game.start()
:ets.insert(:games, {id, pid})
{:reply, {id, pid}, [id | games]}
end
end
def start_link(_) do
GenServer.start_link(__MODULE__, [], name: :dealer)
end
def maybe_create_game(id) do
GenServer.call(:dealer, id)
end
end
每次開始一個新的遊戲,雙方都會想要得到遊戲的 pid
所以統一由一個發牌員來建立,來避免雙方同時各自建立分開的遊戲的情況
再將發牌員放到 lib/card/application.ex
的 start 方法的 children 裡面
def start(_type, _args) do
children = [
# Start the Telemetry supervisor
CardWeb.Telemetry,
# Start the PubSub system
{Phoenix.PubSub, name: Card.PubSub},
# Start the Endpoint (http/https)
CardWeb.Endpoint,
# Start a worker by calling: Card.Worker.start_link(arg)
# {Card.Worker, arg}
Card.Dealer # 加在這裡
]
# 建立 rooms 與 games table 給大家用
:ets.new(:rooms, [:set, :public, :named_table])
:ets.new(:games, [:set, :public, :named_table])
# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: Card.Supervisor]
Supervisor.start_link(children, opts)
end
ok 之後就回來做 mount 方法
defmodule CardWeb.GameLive.Game do
use CardWeb, :live_view
import CardWeb.Component
alias Card.Game
def mount(%{"id" => id} = _params, _session, socket) do
# 請 dealer 給我們一個遊戲
pid = Card.Dealer.find_or_create_game(id)
# 用拿到的 pid 跟 查看遊戲狀態
game = Game.status(pid)
# 把這些資訊存進 assigns 裡面
{:ok, assign(socket, %{pid: pid, id: id, game: game})}
end
# 接著就可以在 畫面上 用 inspect 方法 把原始的資料型態印在網頁上
def render(assigns) do
~H"""
<div class="flex flex-col items-center h-screen">
<.logo />
<%= inspect @game %>
</div>
"""
end
end
建立遊戲後,畫面上會有遊戲剛開始的狀態
如果重新整理,可以看到會依照自動出牌的進度,遊戲狀態有改變
但是我們不可能邊玩邊重新整理
明天來用 pubsub 自動更新遊戲狀態